home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / Software / Freeware / Programare / highlight / highlight-W32GUI-2.2-10b-Setup.exe / {app} / src / ASFormatter.cpp < prev    next >
C/C++ Source or Header  |  2004-06-29  |  55KB  |  1,634 lines

  1. /*
  2.  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
  3.  *
  4.  * ASFormatter.cpp
  5.  * by Tal Davidson (davidsont@bigfoot.com)
  6.  * This file is a part of "Artistic Style" - an indentater and reformatter
  7.  * of C, C++, C# and Java source files.
  8.  *
  9.  * The "Artistic Style" project, including all files needed to compile it,
  10.  * is free software; you can redistribute it and/or use it and/or modify it
  11.  * under the terms of the GNU General Public License as published 
  12.  * by the Free Software Foundation; either version 2 of the License, 
  13.  * or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * You should have received a copy of the GNU General Public
  20.  * License along with this program.
  21.  *
  22.  *
  23.  * Patches:
  24.  * 26 November 1998 - Richard Bullington -
  25.  *        A correction of line-breaking in headers following '}',
  26.  
  27.  *        was created using a variation of a  patch by Richard Bullington.
  28.  * 08 May 2004
  29.  *        applied   ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2,
  30.  *                  patch1_ssvb_patch.tar.gz
  31.  */
  32.  
  33. #include "compiler_defines.h"
  34. #include "ASFormatter.h"
  35.  
  36.  
  37. #include <string>
  38. #include <cctype>
  39. #include <vector>
  40. #include <algorithm>
  41. #include <iostream>
  42.  
  43.  
  44. #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
  45. #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
  46. #define IS_A(a,b)                            ( ((a) & (b)) == (b))
  47. #ifdef USES_NAMESPACE
  48. using namespace std;
  49.  
  50. namespace astyle
  51.   {
  52. #endif
  53.  
  54.  
  55.   bool ASFormatter::calledInitStatic = false;
  56.   vector<const string*> ASFormatter::headers;
  57.   vector<const string*> ASFormatter::nonParenHeaders;
  58.   vector<const string*> ASFormatter::preprocessorHeaders;
  59.   vector<const string*> ASFormatter::preDefinitionHeaders;
  60.   vector<const string*> ASFormatter::preCommandHeaders;
  61.   vector<const string*> ASFormatter::operators;
  62.   vector<const string*> ASFormatter::assignmentOperators;
  63.  
  64.  
  65.   /**
  66.    * Constructor of ASFormatter
  67.    */
  68.   ASFormatter::ASFormatter()
  69.   {
  70.     staticInit();
  71.  
  72.     preBracketHeaderStack = NULL;
  73.     bracketTypeStack = NULL;
  74.     parenStack = NULL;
  75.  
  76.     sourceIterator = NULL;
  77.     bracketFormatMode = NONE_MODE;
  78.     shouldPadOperators = false;
  79.     shouldPadParenthesies = false;
  80.     shouldBreakOneLineBlocks = true;
  81.     shouldBreakOneLineStatements = true;
  82.     shouldConvertTabs = false;
  83.     shouldBreakBlocks = false;
  84.     shouldBreakClosingHeaderBlocks = false;
  85.     shouldBreakClosingHeaderBrackets = false;
  86.     shouldBreakElseIfs = false;
  87.   }
  88.  
  89.   /**
  90.    * Destructor of ASFormatter
  91.    */
  92.   ASFormatter::~ASFormatter()
  93.   {
  94.     DELETE_CONTAINER( preBracketHeaderStack );
  95.   }
  96.  
  97.   /**
  98.    * initialization of static data of ASFormatter.
  99.    */
  100.   void ASFormatter::staticInit()
  101.   {
  102.     if (calledInitStatic)
  103.       return;
  104.  
  105.     calledInitStatic = true;
  106.  
  107.     headers.push_back(&AS_IF);
  108.     headers.push_back(&AS_ELSE);
  109.     headers.push_back(&AS_DO);
  110.     headers.push_back(&AS_WHILE);
  111.     headers.push_back(&AS_FOR);
  112.     headers.push_back(&AS_SYNCHRONIZED);
  113.     headers.push_back(&AS_TRY);
  114.     headers.push_back(&AS_CATCH);
  115.     headers.push_back(&AS_FINALLY);
  116.     headers.push_back(&AS_SWITCH);
  117.     headers.push_back(&AS_TEMPLATE);
  118.     headers.push_back(&AS_FOREACH);
  119.     headers.push_back(&AS_LOCK);
  120.     headers.push_back(&AS_UNSAFE);
  121.     headers.push_back(&AS_FIXED);
  122.     headers.push_back(&AS_GET);
  123.     headers.push_back(&AS_SET);
  124.     headers.push_back(&AS_ADD);
  125.     headers.push_back(&AS_REMOVE);
  126.  
  127.     nonParenHeaders.push_back(&AS_ELSE);
  128.     nonParenHeaders.push_back(&AS_DO);
  129.     nonParenHeaders.push_back(&AS_TRY);
  130.     nonParenHeaders.push_back(&AS_FINALLY);
  131.     nonParenHeaders.push_back(&AS_UNSAFE);
  132.     nonParenHeaders.push_back(&AS_GET);
  133.     nonParenHeaders.push_back(&AS_SET);
  134.     nonParenHeaders.push_back(&AS_ADD);
  135.     nonParenHeaders.push_back(&AS_REMOVE);
  136.  
  137.     //    nonParenHeaders.push_back(&AS_TEMPLATE);
  138.  
  139.     preDefinitionHeaders.push_back(&AS_CLASS);
  140.     preDefinitionHeaders.push_back(&AS_INTERFACE);
  141.     preDefinitionHeaders.push_back(&AS_NAMESPACE);
  142.     preDefinitionHeaders.push_back(&AS_STRUCT);
  143.  
  144.     preCommandHeaders.push_back(&AS_EXTERN);
  145.     preCommandHeaders.push_back(&AS_THROWS);
  146.     preCommandHeaders.push_back(&AS_CONST);
  147.  
  148.     preprocessorHeaders.push_back(&AS_BAR_DEFINE);
  149.     //// DEVEL: removed the folowing lines
  150.     ////preprocessorHeaders.push_back(&AS_BAR_INCLUDE);
  151.     ////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef
  152.     ////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif
  153.     ////preprocessorHeaders.push_back(&AS_BAR_ENDIF);
  154.  
  155.     operators.push_back(&AS_PLUS_ASSIGN);
  156.     operators.push_back(&AS_MINUS_ASSIGN);
  157.     operators.push_back(&AS_MULT_ASSIGN);
  158.     operators.push_back(&AS_DIV_ASSIGN);
  159.     operators.push_back(&AS_MOD_ASSIGN);
  160.     operators.push_back(&AS_OR_ASSIGN);
  161.     operators.push_back(&AS_AND_ASSIGN);
  162.     operators.push_back(&AS_XOR_ASSIGN);
  163.     operators.push_back(&AS_EQUAL);
  164.     operators.push_back(&AS_PLUS_PLUS);
  165.     operators.push_back(&AS_MINUS_MINUS);
  166.     operators.push_back(&AS_NOT_EQUAL);
  167.     operators.push_back(&AS_GR_EQUAL);
  168.     operators.push_back(&AS_GR_GR_GR_ASSIGN);
  169.     operators.push_back(&AS_GR_GR_ASSIGN);
  170.     operators.push_back(&AS_GR_GR_GR);
  171.     operators.push_back(&AS_GR_GR);
  172.     operators.push_back(&AS_LS_EQUAL);
  173.     operators.push_back(&AS_LS_LS_LS_ASSIGN);
  174.     operators.push_back(&AS_LS_LS_ASSIGN);
  175.     operators.push_back(&AS_LS_LS_LS);
  176.     operators.push_back(&AS_LS_LS);
  177.     operators.push_back(&AS_ARROW);
  178.     operators.push_back(&AS_AND);
  179.     operators.push_back(&AS_OR);
  180.     operators.push_back(&AS_COLON_COLON);
  181.  
  182.     //// BUGFIX: removed the folowing lines
  183.     ////    operators.push_back(&AS_PAREN_PAREN);
  184.     ////    operators.push_back(&AS_BLPAREN_BLPAREN);
  185.  
  186.     operators.push_back(&AS_PLUS);
  187.     operators.push_back(&AS_MINUS);
  188.     operators.push_back(&AS_MULT);
  189.     operators.push_back(&AS_DIV);
  190.     operators.push_back(&AS_MOD);
  191.     operators.push_back(&AS_QUESTION);
  192.     operators.push_back(&AS_COLON);
  193.     operators.push_back(&AS_ASSIGN);
  194.     operators.push_back(&AS_LS);
  195.     operators.push_back(&AS_GR);
  196.     operators.push_back(&AS_NOT);
  197.     operators.push_back(&AS_BIT_OR);
  198.     operators.push_back(&AS_BIT_AND);
  199.     operators.push_back(&AS_BIT_NOT);
  200.     operators.push_back(&AS_BIT_XOR);
  201.     operators.push_back(&AS_OPERATOR);
  202.     operators.push_back(&AS_COMMA);
  203.     //BEGIN Content Patch patch1_ssvb_patch.tar.gz
  204.     operators.push_back(&AS_SEMICOLON);
  205.     //END Content Patch patch1_ssvb_patch.tar.gz
  206.     operators.push_back(&AS_RETURN);
  207.  
  208.     assignmentOperators.push_back(&AS_PLUS_ASSIGN);
  209.     assignmentOperators.push_back(&AS_MINUS_ASSIGN);
  210.     assignmentOperators.push_back(&AS_MULT_ASSIGN);
  211.     assignmentOperators.push_back(&AS_DIV_ASSIGN);
  212.     assignmentOperators.push_back(&AS_MOD_ASSIGN);
  213.     assignmentOperators.push_back(&AS_XOR_ASSIGN);
  214.     assignmentOperators.push_back(&AS_OR_ASSIGN);
  215.     assignmentOperators.push_back(&AS_AND_ASSIGN);
  216.     assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
  217.     assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
  218.     assignmentOperators.push_back(&AS_ASSIGN);
  219.   }
  220.  
  221.   /**
  222.    * initialize the ASFormatter.
  223.    *
  224.    * init() should be called every time a ASFormatter object is to start
  225.    * formatting a NEW source file.
  226.    * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
  227.    * that will be used to iterate through the source code. This object will be
  228.    * deleted during the ASFormatter's destruction, and thus should not be
  229.    * deleted elsewhere.
  230.    *
  231.    * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
  232.    */
  233.   void ASFormatter::init(ASSourceIterator *si)
  234.   {
  235.     ASBeautifier::init(si);
  236.     sourceIterator = si;
  237.  
  238.     INIT_CONTAINER( preBracketHeaderStack, new vector<const string*> );
  239.     INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
  240.     bracketTypeStack->push_back(DEFINITION_TYPE);
  241.     INIT_CONTAINER( parenStack, new vector<int> );
  242.     parenStack->push_back(0);
  243.  
  244.     currentHeader = NULL;
  245.     currentLine = string("");
  246.     formattedLine = "";
  247.     currentChar = ' ';
  248.     previousCommandChar = ' ';
  249.     previousNonWSChar = ' ';
  250.     quoteChar = '"';
  251.     charNum = 0;
  252.     previousOperator = NULL;
  253.  
  254.     isVirgin = true;
  255.     isInLineComment = false;
  256.     isInComment = false;
  257.     isInPreprocessor = false;
  258.     doesLineStartComment = false;
  259.     isInQuote = false;
  260.     isSpecialChar = false;
  261.     isNonParenHeader = true;
  262.     foundPreDefinitionHeader = false;
  263.     foundPreCommandHeader = false;
  264.     foundQuestionMark = false;
  265.     isInLineBreak = false;
  266.     endOfCodeReached = false;
  267.     isLineReady = false;
  268.     isPreviousBracketBlockRelated = true;
  269.     isInPotentialCalculation = false;
  270.     //foundOneLineBlock = false;
  271.     shouldReparseCurrentChar = false;
  272.     passedSemicolon = false;
  273.     passedColon = false;
  274.     isInTemplate = false;
  275.     shouldBreakLineAfterComments = false;
  276.     isImmediatelyPostComment = false;
  277.     isImmediatelyPostLineComment = false;
  278.     isImmediatelyPostEmptyBlock = false;
  279.  
  280.     isPrependPostBlockEmptyLineRequested = false;
  281.     isAppendPostBlockEmptyLineRequested = false;
  282.     prependEmptyLine = false;
  283.  
  284.     foundClosingHeader = false;
  285.     previousReadyFormattedLineLength = 0;
  286.  
  287.     isImmediatelyPostHeader = false;
  288.     isInHeader = false;
  289.   }
  290.  
  291.   /**
  292.    * get the next formatted line.
  293.    *
  294.    * @return    formatted line.
  295.    */
  296.  
  297.   string ASFormatter::nextLine()
  298.   {
  299.     const string *newHeader;
  300.     bool isCharImmediatelyPostComment = false;
  301.     bool isPreviousCharPostComment = false;
  302.     bool isCharImmediatelyPostLineComment = false;
  303.     bool isInVirginLine = isVirgin;
  304.     bool isCharImmediatelyPostOpenBlock = false;
  305.     bool isCharImmediatelyPostCloseBlock = false;
  306.     bool isCharImmediatelyPostTemplate = false;
  307.     bool isCharImmediatelyPostHeader = false;
  308.  
  309.     if (!isFormattingEnabled())
  310.       return ASBeautifier::nextLine();
  311.  
  312.     while (!isLineReady)
  313.       {
  314.         if (shouldReparseCurrentChar)
  315.           shouldReparseCurrentChar = false;
  316.         else if (!getNextChar())
  317.           {
  318.             breakLine();
  319.             return beautify(readyFormattedLine);
  320.           }
  321.         else // stuff to do when reading a new character...
  322.           {
  323.             // make sure that a virgin '{' at the begining ofthe file will be treated as a block...
  324.             if (isInVirginLine && currentChar == '{')
  325.               previousCommandChar = '{';
  326.             isPreviousCharPostComment = isCharImmediatelyPostComment;
  327.             isCharImmediatelyPostComment = false;
  328.             isCharImmediatelyPostTemplate = false;
  329.             isCharImmediatelyPostHeader = false;
  330.           }
  331.  
  332.         if (isInLineComment)
  333.           {
  334.             appendCurrentChar();
  335.  
  336.             // explicitely break a line when a line comment's end is found.
  337.             if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length())
  338.               {
  339.                 isInLineBreak = true;
  340.                 isInLineComment = false;
  341.                 isImmediatelyPostLineComment = true;
  342.                 currentChar = 0;  //make sure it is a neutral char.
  343.               }
  344.             continue;
  345.           }
  346.         else if (isInComment)
  347.           {
  348.             if (isSequenceReached(AS_CLOSE_COMMENT))
  349.               {
  350.                 isInComment = false;
  351.                 isImmediatelyPostComment = true;
  352.                 appendSequence(AS_CLOSE_COMMENT);
  353.                 goForward(1);
  354.               }
  355.             else
  356.               appendCurrentChar();
  357.  
  358.             continue;
  359.           }
  360.  
  361.         // not in line comment or comment
  362.  
  363.         else if (isInQuote)
  364.           {
  365.             if (isSpecialChar)
  366.               {
  367.                 isSpecialChar = false;
  368.                 appendCurrentChar();
  369.               }
  370.             else if (currentChar == '\\')
  371.               {
  372.                 isSpecialChar = true;
  373.                 appendCurrentChar();
  374.               }
  375.             else if (quoteChar == currentChar)
  376.               {
  377.                 isInQuote = false;
  378.                 appendCurrentChar();
  379.               }
  380.             else
  381.               {
  382.                 appendCurrentChar();
  383.               }
  384.  
  385.             continue;
  386.           }
  387.  
  388.  
  389.  
  390.         // handle white space - needed to simplify the rest.
  391.         if (isWhiteSpace(currentChar) || isInPreprocessor)
  392.           {
  393.             ////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar()))
  394.             appendCurrentChar();
  395.             continue;
  396.           }
  397.  
  398.         /* not in MIDDLE of quote or comment or white-space of any type ... */
  399.  
  400.         if (isSequenceReached(AS_OPEN_LINE_COMMENT))
  401.           {
  402.             isInLineComment = true;
  403.             if (shouldPadOperators)
  404.               appendSpacePad();
  405.             appendSequence(AS_OPEN_LINE_COMMENT);
  406.             goForward(1);
  407.             continue;
  408.           }
  409.         else if (isSequenceReached(AS_OPEN_COMMENT))
  410.           {
  411.             isInComment = true;
  412.             if (shouldPadOperators)
  413.               appendSpacePad();
  414.             appendSequence(AS_OPEN_COMMENT);
  415.             goForward(1);
  416.             continue;
  417.           }
  418.         else if (currentChar == '"' || currentChar == '\'')
  419.           {
  420.             isInQuote = true;
  421.             quoteChar = currentChar;
  422.             ////            if (shouldPadOperators)  // BUGFIX: these two lines removed. seem to be unneeded, and interfere with L"
  423.             ////                appendSpacePad();    // BUFFIX:    TODO make sure the removal of these lines doesn't reopen old bugs...
  424.             appendCurrentChar();
  425.             continue;
  426.           }
  427.  
  428.         /* not in quote or comment or white-space of any type ... */
  429.  
  430.  
  431.         // check if in preprocessor
  432.         // ** isInPreprocessor will be automatically reset at the begining
  433.         //    of a new line in getnextChar()
  434.         if (currentChar == '#')
  435.           isInPreprocessor = true;
  436.  
  437.         if (isInPreprocessor)
  438.           {
  439.             appendCurrentChar();
  440.             continue;
  441.           }
  442.  
  443.         /* not in preprocessor ... */
  444.  
  445.         if (isImmediatelyPostComment)
  446.           {
  447.             isImmediatelyPostComment = false;
  448.             isCharImmediatelyPostComment = true;
  449.           }
  450.  
  451.         if (isImmediatelyPostLineComment)
  452.           {
  453.             isImmediatelyPostLineComment = false;
  454.             isCharImmediatelyPostLineComment = true;
  455.           }
  456.  
  457.         if (shouldBreakLineAfterComments)
  458.           {
  459.             shouldBreakLineAfterComments = false;
  460.             shouldReparseCurrentChar = true;
  461.             breakLine();
  462.             continue;
  463.           }
  464.  
  465.         // reset isImmediatelyPostHeader information
  466.         if (isImmediatelyPostHeader)
  467.           {
  468.             isImmediatelyPostHeader = false;
  469.             isCharImmediatelyPostHeader = true;
  470.  
  471.             // Make sure headers are broken from their succeeding blocks
  472.             // (e.g.
  473.             //     if (isFoo) DoBar();
  474.             //  should become
  475.             //     if (isFoo)
  476.             //         DoBar;
  477.             // )
  478.             // But treat else if() as a special case which should not be broken!
  479.             if (shouldBreakOneLineStatements)
  480.               {
  481.                 // if may break 'else if()'s, ythen simply break the line
  482.  
  483.                 if (shouldBreakElseIfs)
  484.                   isInLineBreak = true;
  485.  
  486.                 else
  487.                   {
  488.                     // make sure 'else if()'s are not broken.
  489.  
  490.                     bool isInElseIf = false;
  491.                     const string *upcomingHeader;
  492.  
  493.                     upcomingHeader = findHeader(headers);
  494.                     if (currentHeader == &AS_ELSE && upcomingHeader == &AS_IF)
  495.                       isInElseIf = true;
  496.  
  497.                     if (!isInElseIf)
  498.                       isInLineBreak = true;  ////BUGFIX: SHOULD NOT BE breakLine() !!!
  499.                   }
  500.               }
  501.           }
  502.  
  503.         if (passedSemicolon)
  504.           {
  505.             passedSemicolon = false;
  506.             if (parenStack->back() == 0)
  507.               {
  508.                 shouldReparseCurrentChar = true;
  509.                 isInLineBreak = true;
  510.                 continue;
  511.               }
  512.           }
  513.  
  514.         if (passedColon)
  515.           {
  516.             passedColon = false;
  517.             if (parenStack->back() == 0)
  518.               {
  519.                 shouldReparseCurrentChar = true;
  520.                 isInLineBreak = true;
  521.                 continue;
  522.               }
  523.           }
  524.  
  525.         // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
  526.         // If so, set isInTemplate to true
  527.         //
  528.         if (!isInTemplate && currentChar == '<')
  529.           {
  530.             int templateDepth = 0;
  531.             const string *oper;
  532.             for (unsigned int i=charNum;
  533.                  i< currentLine.length();
  534.                  i += (oper ? oper->length() : 1) )
  535.               {
  536.                 oper = ASBeautifier::findHeader(currentLine, i, operators);
  537.  
  538.                 if (oper == &AS_LS)
  539.                   {
  540.                     templateDepth++;
  541.                   }
  542.                 else if (oper == &AS_GR)
  543.                   {
  544.                     templateDepth--;
  545.                     if (templateDepth == 0)
  546.                       {
  547.                         // this is a template!
  548.                         //
  549.                         isInTemplate = true;
  550.                         break;
  551.                       }
  552.                   }
  553.                 else if (oper == &AS_COMMA               // comma,     e.g. A<int, char>
  554.                          || oper == &AS_BIT_AND       // reference, e.g. A<int&>
  555.                          || oper == &AS_MULT          // pointer,   e.g. A<int*>
  556.                          || oper == &AS_COLON_COLON)  // ::,        e.g. std::string
  557.                   {
  558.                     continue;
  559.                   }
  560.                 else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
  561.                   {
  562.                     // this is not a template -> leave...
  563.                     //
  564.                     isInTemplate = false;
  565.                     break;
  566.                   }
  567.               }
  568.           }
  569.  
  570.  
  571.         // handle parenthesies
  572.         //
  573.         if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
  574.           {
  575.             parenStack->back()++;
  576.           }
  577.         else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
  578.           {
  579.             parenStack->back()--;
  580.             if (isInTemplate && parenStack->back() == 0)
  581.               {
  582.                 isInTemplate = false;
  583.                 isCharImmediatelyPostTemplate = true;
  584.               }
  585.  
  586.             // check if this parenthesis closes a header, e.g. if (...), while (...)
  587.             //
  588.             if (isInHeader && parenStack->back() == 0)
  589.               {
  590.                 isInHeader = false;
  591.                 isImmediatelyPostHeader = true;
  592.               }
  593.  
  594.           }
  595.  
  596.         // handle brackets
  597.         //
  598.         BracketType bracketType = NULL_TYPE;
  599.  
  600.         if (currentChar == '{')
  601.           {
  602.             bracketType = getBracketType();
  603.             foundPreDefinitionHeader = false;
  604.             foundPreCommandHeader = false;
  605.  
  606.             bracketTypeStack->push_back(bracketType);
  607.             preBracketHeaderStack->push_back(currentHeader);
  608.             currentHeader = NULL;
  609.  
  610.             isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
  611.           }
  612.         else if (currentChar == '}')
  613.           {
  614.             // if a request has been made to append a post block empty line,
  615.             // but the block exists immediately before a closing bracket,
  616.             // then there is not need for the post block empty line.
  617.             //
  618.             isAppendPostBlockEmptyLineRequested = false;
  619.  
  620.             if (!bracketTypeStack->empty())
  621.               {
  622.                 bracketType = bracketTypeStack->back();
  623.                 bracketTypeStack->pop_back();
  624.  
  625.                 isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
  626.               }
  627.  
  628.             if (!preBracketHeaderStack->empty())
  629.               {
  630.                 currentHeader = preBracketHeaderStack->back();
  631.                 preBracketHeaderStack->pop_back();
  632.               }
  633.             else
  634.               currentHeader = NULL;
  635.           }
  636.  
  637.         if (!IS_A(bracketType, ARRAY_TYPE))
  638.           {
  639.  
  640.             if (currentChar == '{')
  641.               {
  642.                 parenStack->push_back(0);
  643.               }
  644.             else if (currentChar == '}')
  645.               {
  646.                 if (!parenStack->empty())
  647.                   {
  648.                     parenStack->pop_back();
  649.                   }
  650.               }
  651.  
  652.             if (bracketFormatMode != NONE_MODE)
  653.               {
  654.                 if (currentChar == '{')
  655.                   {
  656.                     if ( ( bracketFormatMode == ATTACH_MODE
  657.                            || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
  658.                            && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], COMMAND_TYPE) /*&& isInLineBreak*/)
  659.                          && !isCharImmediatelyPostLineComment )
  660.                       {
  661.                         appendSpacePad();
  662.                         if (!isCharImmediatelyPostComment // do not attach '{' to lines that end with /**/ comments.
  663.                             && previousCommandChar != '{'
  664.                             && previousCommandChar != '}'
  665.                             && previousCommandChar != ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
  666.                           appendCurrentChar(false);
  667.                         else
  668.                           appendCurrentChar(true);
  669.                         continue;
  670.                       }
  671.                     else if (bracketFormatMode == BREAK_MODE
  672.                              || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
  673.                              && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], DEFINITION_TYPE))
  674.                       {
  675.                         if ( shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE) )
  676.                           breakLine();
  677.                         appendCurrentChar();
  678.                         continue;
  679.                       }
  680.                   }
  681.                 else if (currentChar == '}')
  682.                   {
  683.                     // bool origLineBreak = isInLineBreak;
  684.  
  685.                     // mark state of immediately after empty block
  686.                     // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
  687.                     if (previousCommandChar == '{')
  688.                       isImmediatelyPostEmptyBlock = true;
  689.  
  690.                     if ( (!(previousCommandChar == '{' && isPreviousBracketBlockRelated) )          // this '{' does not close an empty block
  691.                          && (shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE))  // astyle is allowed to break on line blocks
  692.                          && !isImmediatelyPostEmptyBlock)                                        // this '}' does not immediately follow an empty block
  693.                       {
  694.                         breakLine();
  695.                         appendCurrentChar();
  696.                       }
  697.                     else
  698.                       {                       
  699.                   // Content Patch    ASFormatter.cpp.patch.bz2
  700.                       // if (!isCharImmediatelyPostComment)
  701.                       if (!isCharImmediatelyPostComment && 
  702.                           !isCharImmediatelyPostLineComment)
  703.                           isInLineBreak = false;
  704.                         appendCurrentChar();
  705.                         if (shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE))
  706.                           shouldBreakLineAfterComments = true;
  707.                       }
  708.  
  709.                     if (shouldBreakBlocks)
  710.                       {
  711.                         isAppendPostBlockEmptyLineRequested =true;
  712.                       }
  713.  
  714.                     continue;
  715.                   }
  716.               }
  717.           }
  718.  
  719.         if ( ( (previousCommandChar == '{'
  720.                 && isPreviousBracketBlockRelated)
  721.  
  722.                || (previousCommandChar == '}'
  723.                    && !isImmediatelyPostEmptyBlock   // <--
  724.                    && isPreviousBracketBlockRelated
  725.                    && !isPreviousCharPostComment    // <-- Fixes wrongly appended newlines after '}' immediately after comments... 10/9/1999
  726.                    && peekNextChar() != ' '))
  727.  
  728.              &&  (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(),  SINGLE_LINE_TYPE)) )
  729.           {
  730.             isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
  731.             isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
  732.  
  733.             previousCommandChar = ' ';
  734.             isInLineBreak = true;  //<----
  735.           }
  736.  
  737.         // reset block handling flags
  738.         isImmediatelyPostEmptyBlock = false;
  739.  
  740.         // look for headers
  741.         if (!isInTemplate)
  742.           {
  743.             if ( (newHeader = findHeader(headers)) != NULL)
  744.               {
  745.                 foundClosingHeader = false;
  746.                 const string *previousHeader;
  747.  
  748.                 // recognize closing headers of do..while, if..else, try..catch..finally
  749.                 if ( (newHeader == &AS_ELSE && currentHeader == &AS_IF)
  750.                      || (newHeader == &AS_WHILE && currentHeader == &AS_DO)
  751.                      || (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
  752.                      || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
  753.                      || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
  754.                      || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH) )
  755.                   foundClosingHeader = true;
  756.  
  757.                 previousHeader = currentHeader;
  758.                 currentHeader = newHeader;
  759.  
  760.                 // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
  761.                 // to their preceding bracket,
  762.                 // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
  763.                 if (!shouldBreakClosingHeaderBrackets && foundClosingHeader && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) && previousNonWSChar == '}')
  764.                   {
  765.                     isInLineBreak = false;
  766.                     appendSpacePad();
  767.  
  768.                     if (shouldBreakBlocks)
  769.                       isAppendPostBlockEmptyLineRequested = false;
  770.                   }
  771.  
  772.                 //Check if a template definition as been reached, e.g. template<class A>
  773.                 if (newHeader == &AS_TEMPLATE)
  774.                   {
  775.                     isInTemplate = true;
  776.                   }
  777.  
  778.                 // check if the found header is non-paren header
  779.                 isNonParenHeader = ( find(nonParenHeaders.begin(), nonParenHeaders.end(),
  780.                                           newHeader) != nonParenHeaders.end() );
  781.                 appendSequence(*currentHeader);
  782.                 goForward(currentHeader->length() - 1);
  783.                 // if padding is on, and a paren-header is found
  784.                 // then add a space pad after it.
  785.                 if (shouldPadOperators && !isNonParenHeader)
  786.                   appendSpacePad();
  787.  
  788.  
  789.                 // Signal that a header has been reached
  790.                 // *** But treat a closing while() (as in do...while)
  791.                 //     as if it where NOT a header since a closing while()
  792.                 //     should never have a block after it!
  793.                 if (!(foundClosingHeader && currentHeader == &AS_WHILE))
  794.                   {
  795.                     isInHeader = true;
  796.                     if (isNonParenHeader)
  797.                       {
  798.                         isImmediatelyPostHeader = true;
  799.                         isInHeader = false;
  800.                       }
  801.                   }
  802.  
  803.                 if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
  804.                   isInLineBreak = false;
  805.  
  806.                 if (shouldBreakBlocks)
  807.                   {
  808.                     if (previousHeader == NULL
  809.                         && !foundClosingHeader
  810.                         && !isCharImmediatelyPostOpenBlock)
  811.                       {
  812.                         isPrependPostBlockEmptyLineRequested = true;
  813.                       }
  814.  
  815.                     if (currentHeader == &AS_ELSE
  816.                         || currentHeader == &AS_CATCH
  817.                         || currentHeader == &AS_FINALLY
  818.                         || foundClosingHeader)
  819.                       {
  820.                         isPrependPostBlockEmptyLineRequested = false;
  821.                       }
  822.  
  823.                     if (shouldBreakClosingHeaderBlocks
  824.                         &&  isCharImmediatelyPostCloseBlock)
  825.                       {
  826.                         isPrependPostBlockEmptyLineRequested = true;
  827.                       }
  828.  
  829.                   }
  830.  
  831.                 continue;
  832.               }
  833.             else if ( (newHeader = findHeader(preDefinitionHeaders)) != NULL)
  834.               {
  835.                 foundPreDefinitionHeader = true;
  836.                 appendSequence(*newHeader);
  837.                 goForward(newHeader->length() - 1);
  838.  
  839.                 if (shouldBreakBlocks)
  840.                   isPrependPostBlockEmptyLineRequested = true;
  841.  
  842.                 continue;
  843.               }
  844.             else if ( (newHeader = findHeader(preCommandHeaders)) != NULL)
  845.               {
  846.                 foundPreCommandHeader = true;
  847.                 appendSequence(*newHeader);
  848.                 goForward(newHeader->length() - 1);
  849.  
  850.                 continue;
  851.               }
  852.           }
  853.  
  854.         if (previousNonWSChar == '}' || currentChar == ';')
  855.           {
  856.             if (shouldBreakOneLineStatements && currentChar == ';'
  857.                 && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(),  SINGLE_LINE_TYPE)))
  858.               {
  859.                 passedSemicolon = true;
  860.               }
  861.  
  862.             if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
  863.               {
  864.                 isAppendPostBlockEmptyLineRequested = true;
  865.               }
  866.  
  867.             if (currentChar != ';')
  868.               currentHeader = NULL; //DEVEL: is this ok?
  869.  
  870.             foundQuestionMark = false;
  871.             foundPreDefinitionHeader = false;
  872.             foundPreCommandHeader = false;
  873.             isInPotentialCalculation = false;
  874.  
  875.           }
  876.  
  877.         if (currentChar == ':'
  878.             && shouldBreakOneLineStatements
  879.             && !foundQuestionMark // not in a ... ? ... : ... sequence
  880.             && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
  881.             && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
  882.             && previousChar != ':' // not part of '::'
  883.             && peekNextChar() != ':') // not part of '::'
  884.           {
  885.             passedColon = true;
  886.             if (shouldBreakBlocks)
  887.               isPrependPostBlockEmptyLineRequested = true;
  888.           }
  889.  
  890.         if (currentChar == '?')
  891.           foundQuestionMark = true;
  892.  
  893.         if (shouldPadOperators)
  894.           {
  895.             if ((newHeader = findHeader(operators)) != NULL)
  896.               {
  897.                 bool shouldPad = (newHeader != &AS_COLON_COLON
  898.                                   && newHeader != &AS_PAREN_PAREN
  899.                                   && newHeader != &AS_BLPAREN_BLPAREN
  900.                                   && newHeader != &AS_PLUS_PLUS
  901.                                   && newHeader != &AS_MINUS_MINUS
  902.                                   && newHeader != &AS_NOT
  903.                                   && newHeader != &AS_BIT_NOT
  904.                                   && newHeader != &AS_ARROW
  905.                                   && newHeader != &AS_OPERATOR
  906.                                   && !(newHeader == &AS_MINUS && isInExponent())
  907.                                   && !(newHeader == &AS_PLUS && isInExponent())
  908.                                   && previousOperator != &AS_OPERATOR
  909.                                   && !((newHeader == &AS_MULT || newHeader == &AS_BIT_AND)
  910.                                        && isPointerOrReference())
  911.                                   && !( (isInTemplate || isCharImmediatelyPostTemplate)
  912.                                         && (newHeader == &AS_LS || newHeader == &AS_GR))
  913.                                  );
  914.  
  915.                 if (!isInPotentialCalculation)
  916.                   if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
  917.                       != assignmentOperators.end())
  918.                     isInPotentialCalculation = true;
  919.  
  920.                 // pad before operator
  921.                 if (shouldPad
  922.                     && !(newHeader == &AS_COLON && !foundQuestionMark)
  923.                     && newHeader != &AS_SEMICOLON
  924.                     && newHeader != &AS_COMMA)
  925.                   appendSpacePad();
  926.                 appendSequence(*newHeader);
  927.                 goForward(newHeader->length() - 1);
  928.  
  929.                 // since this block handles '()' and '[]',
  930.                 // the parenStack must be updated here accordingly!
  931.                 if (newHeader == &AS_PAREN_PAREN
  932.                     || newHeader == &AS_BLPAREN_BLPAREN)
  933.                   parenStack->back()--;
  934.  
  935.                 currentChar = (*newHeader)[newHeader->length() - 1];
  936.                 // pad after operator
  937.                 // but do not pad after a '-' that is a urinary-minus.
  938.                 if ( shouldPad && !(newHeader == &AS_MINUS && isUrinaryMinus()) )
  939.                   appendSpacePad();
  940.  
  941.                 previousOperator = newHeader;
  942.                 continue;
  943.               }
  944.           }
  945.         //BEGIN Content Patch patch1_ssvb_patch.tar.gz
  946.         if (currentChar == '(' || currentChar == '[' ) 
  947.             isInPotentialCalculation = true;
  948.         //END Content Patch patch1_ssvb_patch.tar.gz
  949.         if (shouldPadParenthesies)
  950.           {
  951.             if (currentChar == '(' || currentChar == '[' )
  952.               {
  953.                 char peekedChar = peekNextChar();
  954.  
  955.                 isInPotentialCalculation = true;
  956.                 appendCurrentChar();
  957.                 if (!(currentChar == '(' && peekedChar == ')')
  958.                     && !(currentChar == '[' && peekedChar == ']'))
  959.                   appendSpacePad();
  960.                 continue;
  961.               }
  962.             else if (currentChar == ')' || currentChar == ']')
  963.               {
  964.                 char peekedChar = peekNextChar();
  965.  
  966.                 if (!(previousChar == '(' && currentChar == ')')
  967.                     && !(previousChar == '[' && currentChar == ']'))
  968.                   appendSpacePad();
  969.  
  970.                 appendCurrentChar();
  971.  
  972.                 if (peekedChar != ';' && peekedChar != ',' && peekedChar != '.'
  973.                     && !(currentChar == ']' && peekedChar == '['))
  974.                   appendSpacePad();
  975.                 continue;
  976.               }
  977.           }
  978.  
  979.         appendCurrentChar();
  980.       }
  981.  
  982.     // return a beautified (i.e. correctly indented) line.
  983.  
  984.     string beautifiedLine;
  985.     int readyFormattedLineLength = trim(readyFormattedLine).length();
  986.  
  987.     if (prependEmptyLine
  988.         && readyFormattedLineLength > 0
  989.         && previousReadyFormattedLineLength > 0)
  990.       {
  991.         isLineReady = true; // signal that a readyFormattedLine is still waiting
  992.         beautifiedLine = beautify("");
  993.       }
  994.     else
  995.       {
  996.         isLineReady = false;
  997.         beautifiedLine = beautify(readyFormattedLine);
  998.       }
  999.  
  1000.     prependEmptyLine = false;
  1001.     previousReadyFormattedLineLength = readyFormattedLineLength;
  1002.  
  1003.     return beautifiedLine;
  1004.  
  1005.   }
  1006.  
  1007.  
  1008.   /**
  1009.   * check if there are any indented lines ready to be read by nextLine()
  1010.   *
  1011.   * @return    are there any indented lines ready?
  1012.   */
  1013.   bool ASFormatter::hasMoreLines() const
  1014.     {
  1015.       if (!isFormattingEnabled())
  1016.         return ASBeautifier::hasMoreLines();
  1017.       else
  1018.         return !endOfCodeReached;
  1019.     }
  1020.  
  1021.   /**
  1022.    * check if formatting options are enabled, in addition to indentation.
  1023.    *
  1024.    * @return     are formatting options enabled?
  1025.    */
  1026.   bool ASFormatter::isFormattingEnabled() const
  1027.     {
  1028.       return (bracketFormatMode != NONE_MODE
  1029.               || shouldPadOperators
  1030.               || shouldConvertTabs);
  1031.     }
  1032.  
  1033.   /**
  1034.    * set the bracket formatting mode.
  1035.    * options:
  1036.    *    astyle::NONE_MODE     no formatting of brackets.
  1037.    *    astyle::ATTACH_MODE   Java, K&R style bracket placement.
  1038.    *    astyle::BREAK_MODE    ANSI C/C++ style bracket placement.
  1039.    *
  1040.    * @param mode         the bracket formatting mode.
  1041.    */
  1042.   void ASFormatter::setBracketFormatMode(BracketMode mode)
  1043.   {
  1044.     bracketFormatMode = mode;
  1045.   }
  1046.  
  1047.   /**
  1048.    * set closing header bracket breaking mode
  1049.    * options:
  1050.    *    true     brackets just before closing headers (e.g. 'else', 'catch')
  1051.    *             will be broken, even if standard brackets are attached.
  1052.    *    false    closing header brackets will be treated as standard brackets.
  1053.    *
  1054.    * @param mode         the closing header bracket breaking mode.
  1055.    */
  1056.   void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
  1057.   {
  1058.     shouldBreakClosingHeaderBrackets = state;
  1059.   }
  1060.  
  1061.   /**
  1062.    * set 'else if()' breaking mode
  1063.    * options:
  1064.    *    true     'else' headers will be broken from their succeeding 'if' headers.
  1065.    *    false    'else' headers will be attached to their succeeding 'if' headers.
  1066.    *
  1067.    * @param mode         the 'else if()' breaking mode.
  1068.    */
  1069.   void ASFormatter::setBreakElseIfsMode(bool state)
  1070.   {
  1071.     shouldBreakElseIfs = state;
  1072.   }
  1073.  
  1074.   /**
  1075.    * set operator padding mode.
  1076.    * options:
  1077.    *    true     statement operators will be padded with spaces around them.
  1078.    *    false    statement operators will not be padded.
  1079.    *
  1080.    * @param mode         the padding mode.
  1081.    */
  1082.   void ASFormatter::setOperatorPaddingMode(bool state)
  1083.   {
  1084.     shouldPadOperators = state;
  1085.   }
  1086.  
  1087.   /**
  1088.   * set parentheies padding mode.
  1089.   * options:
  1090.   *    true     statement parenthesies will be padded with spaces around them.
  1091.   *    false    statement parenthesies will not be padded.
  1092.   *
  1093.   * @param mode         the padding mode.
  1094.   */
  1095.   void ASFormatter::setParenthesisPaddingMode(bool state)
  1096.   {
  1097.     shouldPadParenthesies = state;
  1098.   }
  1099.  
  1100.   /**
  1101.    * set option to break/not break one-line blocks
  1102.    *
  1103.    * @param state        true = break, false = don't break.
  1104.    */
  1105.   void ASFormatter::setBreakOneLineBlocksMode(bool state)
  1106.   {
  1107.     shouldBreakOneLineBlocks = state;
  1108.   }
  1109.  
  1110.   /**
  1111.    * set option to break/not break lines consisting of multiple statements.
  1112.    *
  1113.    * @param state        true = break, false = don't break.
  1114.    */
  1115.   void ASFormatter::setSingleStatementsMode(bool state)
  1116.   {
  1117.     shouldBreakOneLineStatements = state;
  1118.   }
  1119.  
  1120.   /**
  1121.    * set option to convert tabs to spaces.
  1122.    *
  1123.    * @param state        true = convert, false = don't convert.
  1124.    */
  1125.   void ASFormatter::setTabSpaceConversionMode(bool state)
  1126.   {
  1127.     shouldConvertTabs = state;
  1128.   }
  1129.  
  1130.  
  1131.   /**
  1132.    * set option to break unrelated blocks of code with empty lines.
  1133.    *
  1134.    * @param state        true = convert, false = don't convert.
  1135.    */
  1136.   void ASFormatter::setBreakBlocksMode(bool state)
  1137.   {
  1138.     shouldBreakBlocks = state;
  1139.   }
  1140.  
  1141.   /**
  1142.    * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
  1143.    *
  1144.    * @param state        true = convert, false = don't convert.
  1145.    */
  1146.   void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
  1147.   {
  1148.     shouldBreakClosingHeaderBlocks = state;
  1149.   }
  1150.  
  1151.   /**
  1152.    * check if a specific sequence exists in the current placement of the current line
  1153.    *
  1154.    * @return             whether sequence has been reached.
  1155.    * @param sequence     the sequence to be checked
  1156.    */
  1157.   bool ASFormatter::isSequenceReached(const string &sequence) const
  1158.     {
  1159.       return currentLine.COMPARE(charNum, sequence.length(), sequence) == 0;
  1160.  
  1161.     }
  1162.  
  1163.   /**
  1164.    * jump over several characters.
  1165.    *
  1166.    * @param i       the number of characters to jump over.
  1167.    */
  1168.   void ASFormatter::goForward(int i)
  1169.   {
  1170.     while (--i >= 0)
  1171.       getNextChar();
  1172.   }
  1173.  
  1174.   /**
  1175.   * peek at the next unread character.
  1176.   *
  1177.   * @return     the next unread character.
  1178.   */
  1179.   char ASFormatter::peekNextChar() const
  1180.     {
  1181.       int peekNum = charNum + 1;
  1182.       int len = currentLine.length();
  1183.       char ch = ' ';
  1184.  
  1185.       while (peekNum < len)
  1186.         {
  1187.           ch = currentLine[peekNum++];
  1188.           if (!isWhiteSpace(ch))
  1189.             return ch;
  1190.         }
  1191.  
  1192.       if (shouldConvertTabs && ch == '\t')
  1193.         ch = ' ';
  1194.  
  1195.       return ch;
  1196.     }
  1197.  
  1198.   /**
  1199.   * check if current placement is before a comment or line-comment
  1200.   *
  1201.   * @return     is before a comment or line-comment.
  1202.   */
  1203.   bool ASFormatter::isBeforeComment() const
  1204.     {
  1205.       int peekNum = charNum + 1;
  1206.       int len = currentLine.length();
  1207.       // char ch = ' ';
  1208.       bool foundComment = false;
  1209.  
  1210.       for (peekNum = charNum + 1;
  1211.            peekNum < len && isWhiteSpace(currentLine[peekNum]);
  1212.            ++peekNum)
  1213.         ;
  1214.  
  1215.       if (peekNum < len)
  1216.         foundComment = ( currentLine.COMPARE(peekNum, 2, AS_OPEN_COMMENT) == 0
  1217.                          || currentLine.COMPARE(peekNum, 2, AS_OPEN_LINE_COMMENT) == 0 );
  1218.  
  1219.       return foundComment;
  1220.     }
  1221.  
  1222.   /**
  1223.   * get the next character, increasing the current placement in the process.
  1224.   * the new character is inserted into the variable currentChar.
  1225.   *
  1226.   * @return   whether succeded to recieve the new character.
  1227.   */
  1228.   bool ASFormatter::getNextChar()
  1229.   {
  1230.     isInLineBreak = false;
  1231.     bool isAfterFormattedWhiteSpace = false;
  1232.  
  1233.     if (shouldPadOperators && !isInComment && !isInLineComment
  1234.         && !isInQuote && !doesLineStartComment && !isInPreprocessor
  1235.         && !isBeforeComment())
  1236.       {
  1237.       //BEGIN Content Patch patch1_ssvb_patch.tar.gz
  1238.         char prevchar = ' ';
  1239.         char nextchar = peekNextChar();
  1240.         
  1241.         int len = formattedLine.length();
  1242.        // if (len > 0 && isWhiteSpace(formattedLine[len-1]))
  1243.        if (len > 0) prevchar = formattedLine[len-1];
  1244.         if (isWhiteSpace(prevchar) || prevchar == '(' || prevchar == '[' || 
  1245.                 nextchar == ')' || nextchar == ']')
  1246.         {
  1247.           isAfterFormattedWhiteSpace = true;
  1248.         }
  1249.         //END Content Patch patch1_ssvb_patch.tar.gz
  1250.       }
  1251.  
  1252.     previousChar = currentChar;
  1253.     if (!isWhiteSpace(currentChar))
  1254.       {
  1255.         previousNonWSChar = currentChar;
  1256.         if (!isInComment && !isInLineComment && !isInQuote
  1257.             && !isSequenceReached(AS_OPEN_COMMENT)
  1258.             && !isSequenceReached(AS_OPEN_LINE_COMMENT) )
  1259.           previousCommandChar = previousNonWSChar;
  1260.       }
  1261.  
  1262.     unsigned int currentLineLength = currentLine.length();
  1263.  
  1264.     if (charNum+1 < currentLineLength
  1265.         && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
  1266.       {
  1267.         currentChar = currentLine[++charNum];
  1268.         if (isAfterFormattedWhiteSpace)
  1269.           while (isWhiteSpace(currentChar) && charNum+1 < currentLineLength)
  1270.             currentChar = currentLine[++charNum];
  1271.  
  1272.         if (shouldConvertTabs && currentChar == '\t')
  1273.           currentChar = ' ';
  1274.  
  1275.         return true;
  1276.       }
  1277.     // BEGIN Content patch ASFormatter450670.patch.bz2
  1278.     else if (isInLineComment &&  (charNum+1 == currentLineLength))
  1279.     {
  1280.         // fix BUG #450670
  1281.       currentChar = ' ';  
  1282.       return true;
  1283.     }
  1284.     // END Content patch ASFormatter450670.patch.bz2  
  1285.     else
  1286.       {
  1287.         if (sourceIterator->hasMoreLines())
  1288.           {
  1289.             currentLine = sourceIterator->nextLine();
  1290.             if (currentLine.length() == 0)
  1291.               {
  1292.                 /*think*/ currentLine = string(" ");
  1293.               }
  1294.  
  1295.             // unless reading in the first line of the file,
  1296.             // break a new line.
  1297.             if (!isVirgin)
  1298.               isInLineBreak = true;
  1299.             else
  1300.               isVirgin = false;
  1301.  
  1302.             if (isInLineComment)
  1303.               isImmediatelyPostLineComment = true;
  1304.             isInLineComment = false;
  1305.  
  1306.             trimNewLine();
  1307.             currentChar = currentLine[charNum];
  1308.  
  1309.             // check if is in preprocessor right after the line break and line trimming
  1310.             if (previousNonWSChar != '\\')
  1311.               isInPreprocessor = false;
  1312.  
  1313.             if (shouldConvertTabs && currentChar == '\t')
  1314.               currentChar = ' ';
  1315.  
  1316.             return true;
  1317.           }
  1318.         else
  1319.           {
  1320.             endOfCodeReached = true;
  1321.             return false;
  1322.           }
  1323.       }
  1324.   }
  1325.  
  1326.   /**
  1327.   * jump over the leading white space in the current line,
  1328.   * IF the line does not begin a comment or is in a preprocessor definition.
  1329.   */
  1330.   void ASFormatter::trimNewLine()
  1331.   {
  1332.     unsigned int len = currentLine.length();
  1333.     charNum = 0;
  1334.  
  1335.     if (isInComment || isInPreprocessor)
  1336.       return;
  1337.  
  1338.     while (isWhiteSpace(currentLine[charNum]) && charNum+1 < len)
  1339.       ++charNum;
  1340.  
  1341.     doesLineStartComment = false;
  1342.     if (isSequenceReached(string("/*")))
  1343.       {
  1344.         charNum = 0;
  1345.         doesLineStartComment = true;
  1346.       }
  1347.   }
  1348.  
  1349.   /**
  1350.    * append a character to the current formatted line.
  1351.    * Unless disabled (via canBreakLine == false), first check if a 
  1352.    * line-break has been registered, and if so break the 
  1353.    * formatted line, and only then append the character into
  1354.    * the next formatted line.
  1355.    *
  1356.    * @param ch               the character to append.
  1357.    * @param canBreakLine     if true, a registered line-break
  1358.    */
  1359.   void ASFormatter::appendChar(char ch, bool canBreakLine)
  1360.   {
  1361.     if (canBreakLine && isInLineBreak)
  1362.       breakLine();
  1363.     formattedLine.append(1, ch);
  1364.   }
  1365.  
  1366.   /**
  1367.    * append the CURRENT character (curentChar)to the current
  1368.    * formatted line. Unless disabled (via canBreakLine == false),
  1369.    * first check if a line-break has been registered, and if so
  1370.    * break the formatted line, and only then append the character
  1371.    * into the next formatted line.
  1372.    *
  1373.    * @param canBreakLine     if true, a registered line-break
  1374.    */
  1375.   void ASFormatter::appendCurrentChar(bool canBreakLine)
  1376.   {
  1377.     appendChar(currentChar, canBreakLine);
  1378.   }
  1379.  
  1380.   /**
  1381.    * append a string sequence to the current formatted line.
  1382.    * Unless disabled (via canBreakLine == false), first check if a 
  1383.    * line-break has been registered, and if so break the 
  1384.    * formatted line, and only then append the sequence into
  1385.    * the next formatted line.
  1386.    *
  1387.    * @param sequence         the sequence to append.
  1388.    * @param canBreakLine     if true, a registered line-break
  1389.    */
  1390.   void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
  1391.   {
  1392.     if (canBreakLine && isInLineBreak)
  1393.       breakLine();
  1394.     formattedLine.append(sequence);
  1395.   }
  1396.  
  1397.   /**
  1398.    * append a space to the current formattedline, UNLESS the 
  1399.    * last character is already a white-space character.
  1400.    */
  1401.   void ASFormatter::appendSpacePad()
  1402.   {
  1403.     int len = formattedLine.length();
  1404.     if (len == 0 || !isWhiteSpace(formattedLine[len-1]))
  1405.       formattedLine.append(1, ' ');
  1406.   }
  1407.  
  1408.   /**
  1409.    * register a line break for the formatted line.
  1410.    */
  1411.   void ASFormatter::breakLine()
  1412.   {
  1413.     isLineReady = true;
  1414.     isInLineBreak = false;
  1415.  
  1416.     // queue an empty line prepend request if one exists
  1417.     prependEmptyLine = isPrependPostBlockEmptyLineRequested;
  1418.  
  1419.     readyFormattedLine =  formattedLine;
  1420.     if (isAppendPostBlockEmptyLineRequested)
  1421.       {
  1422.         isAppendPostBlockEmptyLineRequested = false;
  1423.         isPrependPostBlockEmptyLineRequested = true;
  1424.       }
  1425.     else
  1426.       {
  1427.         isPrependPostBlockEmptyLineRequested = false;
  1428.       }
  1429.  
  1430.     formattedLine = "";
  1431.   }
  1432.  
  1433.   /**
  1434.    * check if the currently reached open-bracket (i.e. '{')
  1435.    * opens a:
  1436.    * - a definition type block (such as a class or namespace),
  1437.    * - a command block (such as a method block)
  1438.    * - a static array
  1439.    * this method takes for granted that the current character
  1440.    * is an opening bracket.
  1441.    *
  1442.    * @return    the type of the opened block.
  1443.    */
  1444.   BracketType ASFormatter::getBracketType() const
  1445.     {
  1446.       BracketType returnVal;
  1447.  
  1448.       if (foundPreDefinitionHeader)
  1449.         returnVal = DEFINITION_TYPE;
  1450.       else
  1451.         {
  1452.           bool isCommandType;
  1453.           isCommandType = ( foundPreCommandHeader
  1454.                             || ( currentHeader != NULL && isNonParenHeader )
  1455.                             || ( previousCommandChar == ')' )
  1456.                             || ( previousCommandChar == ':' && !foundQuestionMark )
  1457.                             || ( previousCommandChar == ';' )
  1458.                             || ( ( previousCommandChar == '{' ||  previousCommandChar == '}')
  1459.                                  && isPreviousBracketBlockRelated ) );
  1460.  
  1461.           returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
  1462.         }
  1463.  
  1464.       if (isOneLineBlockReached())
  1465.         returnVal = (BracketType) (returnVal | SINGLE_LINE_TYPE);
  1466.  
  1467.       return returnVal;
  1468.     }
  1469.  
  1470.   /**
  1471.    * check if the currently reached  '*' or '&' character is
  1472.    * a pointer-or-reference symbol, or another operator.
  1473.    * this method takes for granted that the current character
  1474.    * is either a '*' or '&'.
  1475.    *
  1476.    * @return        whether current character is a reference-or-pointer 
  1477.    */
  1478.   bool ASFormatter::isPointerOrReference() const
  1479.     {
  1480.       bool isPR;
  1481.       isPR = ( !isInPotentialCalculation
  1482.                || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
  1483.                || (!isLegalNameChar(previousNonWSChar)
  1484.                    && previousNonWSChar != ')'
  1485.                    && previousNonWSChar != ']')
  1486.              );
  1487.  
  1488.       if (!isPR)
  1489.         {
  1490.           char nextChar = peekNextChar();
  1491.           isPR |= (!isWhiteSpace(nextChar)
  1492.                    && nextChar != '-'
  1493.                    && nextChar != '('
  1494.                    && nextChar != '['
  1495.                    && !isLegalNameChar(nextChar));
  1496.         }
  1497.  
  1498.       return isPR;
  1499.     }
  1500.  
  1501.  
  1502.   /**
  1503.    * check if the currently reached '-' character is
  1504.    * a urinary minus
  1505.    * this method takes for granted that the current character
  1506.    * is a '-'.
  1507.    *
  1508.    * @return        whether the current '-' is a urinary minus.
  1509.    */
  1510.   bool ASFormatter::isUrinaryMinus() const
  1511.     {
  1512.       return ( (previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
  1513.                && previousCommandChar != '.'
  1514.                && previousCommandChar != ')'
  1515.                && previousCommandChar != ']' );
  1516.     }
  1517.  
  1518.  
  1519.   /**
  1520.    * check if the currently reached '-' or '+' character is
  1521.    * part of an exponent, i.e. 0.2E-5.
  1522.    * this method takes for granted that the current character
  1523.    * is a '-' or '+'.
  1524.    *
  1525.    * @return        whether the current '-' is in an exponent.
  1526.    */
  1527.   bool ASFormatter::isInExponent() const
  1528.     {
  1529.       int formattedLineLength = formattedLine.length();
  1530.       if (formattedLineLength >= 2)
  1531.         {
  1532.           char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
  1533.           char prevFormattedChar = formattedLine[formattedLineLength - 1];
  1534.  
  1535.           return ( (prevFormattedChar == 'e' || prevFormattedChar == 'E')
  1536.                    && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)) );
  1537.         }
  1538.       else
  1539.         return false;
  1540.     }
  1541.  
  1542.   /**
  1543.    * check if a one-line bracket has been reached,
  1544.    * i.e. if the currently reached '{' character is closed
  1545.    * with a complimentry '}' elsewhere on the current line,
  1546.    *.
  1547.    * @return        has a one-line bracket been reached?
  1548.    */
  1549.   bool ASFormatter::isOneLineBlockReached() const
  1550.     {
  1551.       bool isInComment = false;
  1552.       bool isInQuote = false;
  1553.       int bracketCount = 1;
  1554.       int currentLineLength = currentLine.length();
  1555.       int i = 0;
  1556.       char ch = ' ';
  1557.       char quoteChar = ' ';
  1558.  
  1559.       for (i = charNum + 1; i < currentLineLength; ++i)
  1560.         {
  1561.           ch = currentLine[i];
  1562.  
  1563.           if (isInComment)
  1564.             {
  1565.               if (currentLine.COMPARE(i, 2, "*/") == 0)
  1566.                 {
  1567.                   isInComment = false;
  1568.                   ++i;
  1569.                 }
  1570.               continue;
  1571.             }
  1572.  
  1573.           if (ch == '\\')
  1574.             {
  1575.               ++i;
  1576.               continue;
  1577.             }
  1578.  
  1579.           if (isInQuote)
  1580.             {
  1581.               if (ch == quoteChar)
  1582.                 isInQuote = false;
  1583.               continue;
  1584.             }
  1585.  
  1586.           if (ch == '"' || ch == '\'')
  1587.             {
  1588.               isInQuote = true;
  1589.               quoteChar = ch;
  1590.               continue;
  1591.             }
  1592.  
  1593.           if (currentLine.COMPARE(i, 2, "//") == 0)
  1594.             break;
  1595.  
  1596.           if (currentLine.COMPARE(i, 2, "/*") == 0)
  1597.             {
  1598.               isInComment = true;
  1599.               ++i;
  1600.               continue;
  1601.             }
  1602.  
  1603.           if (ch == '{')
  1604.             ++bracketCount;
  1605.           else if (ch == '}')
  1606.             --bracketCount;
  1607.  
  1608.           if(bracketCount == 0)
  1609.             return true;
  1610.         }
  1611.  
  1612.       return false;
  1613.     }
  1614.  
  1615.  
  1616.   /**
  1617.    * check if one of a set of headers has been reached in the
  1618.    * current position of the current line.
  1619.    *
  1620.    * @return             a pointer to the found header. Or a NULL if no header has been reached.
  1621.    * @param headers      a vector of headers
  1622.    * @param checkBoundry 
  1623.    */
  1624.   const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
  1625.   {
  1626.     return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
  1627.   }
  1628.  
  1629.  
  1630.  
  1631. #ifdef USES_NAMESPACE
  1632. }
  1633. #endif
  1634.